﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

// C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.Client;

// Reference Common project
using Microsoft.DPE.UK.TFS.EmbeddedWorkItems.Common;

namespace Microsoft.DPE.UK.TFS.EmbeddedWorkItems
{
    /// <summary>
    /// THis policy is designed to check that work items have been added to a check-in comment, and that they are valid.
    /// An event handler will actually associate the work items with a change set
    /// 
    /// Notes:
    /// 
    /// On 64 bit the correct registry key is:
    /// HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\TeamFoundation\SourceControl\Checkin Policies
    /// 
    /// Add a new String Value with the key being the name of the policy assembly and the value being the full path including the dll name
    /// 
    /// The class must be Serializable and public.
    /// </summary>
    [Serializable]
    public class EmbeddedWorkItemPolicy : PolicyBase
    {
        private string _policyDescription = "Associate with work items by listing them in a check-in comment.";
        // This returns the brief description of the policy itself in the Policy Type column of the selected policies
        private string _type = "Work Item In Comments Policy";
        // This returns the description displayed in the Check In Policy selection dialog
        private string _typeDescription = "This policy requires one or more work items to be associated with every check-in by listing the work item ids inside square brackets within the check-in comments.";

        //Errors
        private string _noComment = "You did not enter a check in comment. Please enter a comment including valid work items in the form [123].";
        private string _noWorkItems = "Your comment does not contain any valid work items. Please enter valid work items in the form [123].";
        private string _invalidWorkItems = "Your comment contains the following invalid work items: ";

        public override string Description
        {
            get { return _policyDescription; }
        }

        public override bool Edit(IPolicyEditArgs policyEditArgs)
        {
            // No config UI
            // Could configure; start and end markers, behaviour if no work items, associate vs resolve work items
            return true;
        }

        public override PolicyFailure[] Evaluate()
        {
            // Get the check-in comment
            string checkinComment = PendingCheckin.PendingChanges.Comment;
            if (checkinComment == null || checkinComment.Length == 0)
            {
                return new PolicyFailure[] { new PolicyFailure(_noComment, this) };
            }

            // Get any work items from comments
			int[] workItemIds = Logic.getWorkItemIds(checkinComment);
            List<int> invalidWorkItems = new List<int>();

			// Only continue if there some work items to associate
			if (workItemIds.Length > 0)
			{
				// Get a reference to the work item store
                var workItemStore = (WorkItemStore)PendingCheckin.GetService(typeof(WorkItemStore));
				
				// For each work item in the list add a link to the changes
				for (int i = 0; i < workItemIds.Length; i++)
				{
					try 
					{
						// Get the workitem in order to validate that it exists
                        WorkItem wi = workItemStore.GetWorkItem(workItemIds[i]);
					}
					catch (Exception ex)
					{
				        // It can't be found, not a valid WorkItem
                        invalidWorkItems.Add(workItemIds[i]);
                    }	
				}
			}
            else
            {
                // No recognisable work items in the comments
                return new PolicyFailure[] { new PolicyFailure(_noWorkItems, this) };
            }

            if (invalidWorkItems.Count > 0)
            {
                string invalidWIs = "";
                foreach (int item in invalidWorkItems)
                {
                    invalidWIs += item + " ";
                }
                return new PolicyFailure[] { new PolicyFailure(_invalidWorkItems + invalidWIs, this) };
            }
            else
            {
                // No issues with the work items in the comment
                return new PolicyFailure[0];
            }
        }

        public override string Type
        {
            get { return _type; }
        }

        public override string TypeDescription
        {
            get { return _typeDescription; }
        }
    }
}
